using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//定时器
public class Timer
{
    //时间间隔
    private float m_Interval;
    //循环次数
    private int m_Loop;
    //定时器回调
    private Action m_TimerCallback;
    //受TimeScale影响
    private bool m_IsTimeScale;
    //运行中
    private bool m_Running;
    //fixed执行
    private bool m_IsFixed;
    //下次执行时间
    private float time;
    //是否帧执行
    private bool m_IsFrame;
    public bool IsTimeScale => m_IsTimeScale;
    public bool IsFixed => m_IsFixed;
    //id
    private int m_id;
    public int ID => m_id;
    private bool m_dirty;
    public bool Dirty => m_dirty;

    public Timer(int id,Action func,float interval,int loop = -1,bool is_timescale = false,bool is_frame = false,bool is_fixed = false){
        id = m_id;
        m_TimerCallback = func;
        m_Interval = interval;
        m_Loop = loop;
        m_IsTimeScale = is_timescale;
        m_IsFrame = is_frame;
        m_IsFixed = is_fixed;
        time = m_Interval;
        m_Running = false;
        m_dirty = false;

    }

    public void Update(float deltaTime){

        if(m_dirty){
            Stop();
            return;
        }
        if(m_Running)
        {
            if(m_IsFrame)
            {
                time -= 1;      //帧执行
            }else{
                time -= deltaTime;  //定时执行
            }
            
            
            if(time <= 0){

                // if(m_Loop != 0)
                    m_TimerCallback?.Invoke();

                if(m_Loop == 0)
                {
                    Stop();
                }else if(m_Loop == -1){
                    time = m_Interval;
                }else{
                    m_Loop -= 1;
                    time = m_Interval;
                }
            }
            
        }
    }

    public void Start()
    {
        m_Running = true;
    }

    public void Pause(bool b){
        m_Running = !b;
    }
    public void Stop(){
        m_dirty = true;
        m_Running = false;
        TimerMgr.Instance.RemoveTimer(this);
    }

}

//定时器管理器
public class TimerMgr : SingletonMono<TimerMgr>
{
    //固定帧定时器列表
    private List<Timer> m_FixedTimerList = new List<Timer>();
    //定时器列表
    private List<Timer> m_TimerList = new List<Timer>();
    //添加列表
    private List<Timer> m_AddList = new List<Timer>();
    //移除列表
    private List<Timer> m_RemoveList = new List<Timer>();
    private static int m_id = 0;
    

    /// <summary>
    /// 添加定时器
    /// </summary>
    /// <param name="func">回调函数</param>
    /// <param name="interval">时间间隔</param>
    /// <param name="loop">循环次数 -1 无限循环</param>
    /// <param name="is_timescale">是否受TimeScale影响</param>
    /// <param name="is_frame">是否帧执行</param>
    /// <param name="is_fixed">是否固定帧执行</param>
    /// <returns></returns>
    public Timer AddTimer(Action func,float interval,int loop = -1,bool is_timescale = false,bool is_frame = false,bool is_fixed = false)
    {
        Timer timer = new Timer(m_id,func,interval,loop,is_timescale,is_frame,is_fixed);
        m_id += 1;
        m_AddList.Add(timer);
        return timer;
    }

    //移除定时器
    public void RemoveTimer(Timer timer)
    {
        if(timer.IsFixed)
        {
            m_FixedTimerList.Remove(timer);
        }else{
            m_TimerList.Remove(timer);
        }
        m_RemoveList.Add(timer);
    }

    public override void Init()
    {
        base.Init();
        Debug.Log("init timermgr");
    }

    //更新
    public void Update()
    {
        foreach(Timer timer in m_TimerList)
        {
            float time = timer.IsTimeScale ? Time.deltaTime : Time.unscaledDeltaTime;
            timer.Update(time);
        }
    }

    //fixedUpdate   
    public void FixedUpdate(){
        foreach(Timer timer in m_FixedTimerList)
        {
            float time = timer.IsTimeScale ? Time.fixedDeltaTime : Time.fixedUnscaledDeltaTime;
            timer.Update(time);
        }
    }

    public void LateUpdate()
    {
        for(int i = 0;i < m_RemoveList.Count;i++)
        {
            m_RemoveList[i] = null;
        }
        m_RemoveList.Clear();
        // Debug.Log("m_TimerList.Count = " + m_TimerList.Count);
        // Debug.Log("m_FixedTimerList.Count = " + m_FixedTimerList.Count);
        foreach(Timer timer in m_AddList)
        {
            if(timer.IsFixed)
            {
                m_FixedTimerList.Add(timer);
            }else{
                m_TimerList.Add(timer);
            }
        }
        m_AddList.Clear();
    }
}
